
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;

using Swaf.Call;


namespace Swaf.Logging
{
	/// <summary>
	/// Summary description for BaseLog.
	/// </summary>
	public class BaseLog
	{
		ICallbackQueue m_callbackQueue;
		protected IList m_observers;
		protected IList m_buffer= new ArrayList();
		protected int m_notifyThreshold=1;
		protected bool m_logCaller=false;

		public BaseLog(string groupName)
		{
			m_callbackQueue = new ThreadedCallbackQueue(groupName);
			m_observers = new ArrayList();
		}
		public IList Observers {get {return m_observers;}}
		public void addObserver(ICall observer)
		{
			addObserver(observer, m_notifyThreshold,true);
		}
		public void addObserver(ICall observer, int notifyThreshold, bool allowStartupLogging)
		{
			ICall newObserver=new LogCall(observer,notifyThreshold,allowStartupLogging);
			lock(m_observers)
			{
				m_observers.Add(newObserver);
			}
			//If log calls were made prior to registering this observer, we need to send 
			//them to this observer.
			if (m_buffer.Count > 0)
			{
				foreach(IDictionary info in m_buffer)
				{
					int level = (int) info["level"];
					if(!(m_notifyThreshold < 0 || m_notifyThreshold > level))
					{
						m_callbackQueue.enqueueCall(newObserver, info);
					}
				}
			}
		}

		protected virtual void notifyObservers(IDictionary info)
		{
			lock(m_observers)
			{
				foreach(ICall observer in m_observers)
				{
					m_callbackQueue.enqueueCall(observer, info);
				}
			}
		}
	}

    public class LogCall:ICall
	{
		protected ICall m_internalCall=null;
		protected int m_notifyThreshold=1;
		protected int m_tmpNotifyThreshold=-1;
		protected bool m_notifyOverridden=false;
		protected bool m_defaultOverride = false;
		protected bool m_allowStartupLogging = true;
		public LogCall(ICall internalCall, int logThresholdLevel, bool allowStartupLogging)
		{
			m_internalCall = internalCall;
			m_allowStartupLogging=allowStartupLogging;
			m_defaultOverride = true;
			startupLoggingLevel = Application.currentApp.Log.NotifyThreshold;

			if (logThresholdLevel != -1)
			{
				m_notifyThreshold = logThresholdLevel;
			}
			else
				m_notifyThreshold = Application.currentApp.Log.DefaultLevel;
			

		}
		public int startupLoggingLevel 
		{
			set 
			{
				if (m_allowStartupLogging)
				{
					m_tmpNotifyThreshold = m_notifyThreshold;
					m_notifyOverridden  = true;
					m_notifyThreshold = value;
				}
			}
		}
		public void startupComplete()
		{
			if (m_notifyOverridden)
			{
				m_notifyThreshold = m_tmpNotifyThreshold;
				m_notifyOverridden =false;
			}
		}
		#region ICall Members

		public Swaf.Call.CallParamOption ParamHandling
		{
			get
			{
				// TODO:  Add LogCall.ParamHandling getter implementation
				return new Swaf.Call.CallParamOption ();
			}
			set
			{
				// TODO:  Add LogCall.ParamHandling setter implementation
			}
		}

		public string Id
		{
			get
			{
				// TODO:  Add LogCall.Id getter implementation
				return null;
			}
		}

		public string Method {get{return "";}}

		public bool WorksWithMultiCall
		{
			get
			{
				// TODO:  Add LogCall.WorksWithMultiCall getter implementation
				return false;
			}
		}

		public object call(params object[] p)
		{
			IDictionary info = (IDictionary) p[0];
			int level=-1;
			//If we are in startup and this observer has been configured
			//to not allow startup, then we must not allow the logging, regardless of 
			//the levels!
			if (((bool) info["isStartup"]) && !m_allowStartupLogging)
				return null;

			if (info.Contains("level"))
				level = (int) info["level"];
			if(!(m_notifyThreshold < 0 || m_notifyThreshold > level))
                return m_internalCall.call(p);
			else
				return null;
		}

		public object[] CallParams
		{
			get
			{
				// TODO:  Add LogCall.CallParams getter implementation
				return null;
			}
			set
			{
				// TODO:  Add LogCall.CallParams setter implementation
			}
		}

		public Swaf.Call.CallDistanceType CallDistance
		{
			get
			{
				// TODO:  Add LogCall.CallDistance getter implementation
				return new Swaf.Call.CallDistanceType ();
			}
		}

		#endregion

	}

}
